package ru.spb.osll.myfit.client.view;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import ru.spb.osll.myfit.client.dialog.ErrorDialog;
import ru.spb.osll.myfit.client.manager.PageExecutingManager;
import ru.spb.osll.myfit.client.manager.SuiteExecutingManager;
import ru.spb.osll.myfit.client.service.PageExecutingService;
import ru.spb.osll.myfit.client.service.PageExecutingServiceAsync;
import ru.spb.osll.myfit.client.service.SuiteExecutingService;
import ru.spb.osll.myfit.client.service.SuiteExecutingServiceAsync;
import ru.spb.osll.myfit.client.widget.ExecutingListener;
import ru.spb.osll.myfit.common.ExecutingResult;
import ru.spb.osll.myfit.common.MetadataColumnDef;
import ru.spb.osll.myfit.common.SuiteExecutingResult;
import ru.spb.osll.myfit.client.widget.filter.FiltrationWidget;
import ru.spb.osll.myfit.common.filter.FilterSerializer;
import ru.spb.osll.myfit.common.filter.PageResultFilter;


import java.util.*;

public class TestTableViewController implements IViewController {

  private ErrorDialog m_errorDialog = new ErrorDialog();
  /**
   * Create a remote service proxy to talk to the server-side Fit service.
   */
  private final PageExecutingServiceAsync m_pageExecutingService =
                                  GWT.create(PageExecutingService.class);

  private final SuiteExecutingServiceAsync m_suiteExecutingService = GWT.create(SuiteExecutingService.class);

  @Override
  public IView getView(String address) {
    final TestTableView view = new TestTableView();
    String filtersString = Window.Location.getParameter("filter");

    PageExecutingManager pageExecutingManager = new PageExecutingManager();
    SuiteExecutingManager suiteExecutingManager = new SuiteExecutingManager();

    List<PageResultFilter> filters = new FilterSerializer().deserialize(filtersString);
    final FiltrationWidget filtrationWidget = view.getFiltrationWidget();
    filtrationWidget.addFilters(filters);


    filtrationWidget.addFilterClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent clickEvent) {
        List<PageResultFilter> filters = filtrationWidget.getFilters();
        FilterSerializer serializer = new FilterSerializer();
        String address = ViewConstants.TEST_TABLE_ADDRESS;

        if (filters.size() > 0) {
          address += "?filter=" + serializer.serialize(filters);
        }
        Window.Location.assign(address);
      }
    });

    ExecutingListener executingListener = new ExecutingListener() {
      @Override
      public void processExecutingResult(ExecutingResult result) {
        view.updateResult(result);
      }

      @Override
      public void finish() {
      }
    };

    addMetadataColumns(view);
    addResults(view, pageExecutingManager, suiteExecutingManager, executingListener, filtersString);
    return view;
  }

  private void addMetadataColumns(final TestTableView view) {
    m_pageExecutingService.getMetadataColDef(new AsyncCallback<List<MetadataColumnDef>>() {
      @Override
      public void onFailure(Throwable caught) {
        m_errorDialog.setMessage(caught);
        m_errorDialog.center();
      }

      @Override
      public void onSuccess(List<MetadataColumnDef> metadataColDef) {
        for (MetadataColumnDef def : metadataColDef) {
          view.createMetadataCol(def);
        }
        view.refresh();
      }
    });
  }

  private void addResults(final TestTableView view, final PageExecutingManager pageExecutingManager, final SuiteExecutingManager suiteExecutingManager,
                          final ExecutingListener executingListener, final String filtersString) {
    m_pageExecutingService.getTestResultHeaders(filtersString, new AsyncCallback<Set<ExecutingResult>>() {
      public void onFailure(Throwable caught) {
        m_errorDialog.setMessage(caught);
        m_errorDialog.center();
      }

      public void onSuccess(Set<ExecutingResult> list) {
        List<ExecutingResult> results = new LinkedList<ExecutingResult>(list);
        view.addResultToWidget(results);
        for (ExecutingResult result : list) {
          pageExecutingManager.addResultToListen(result);
          pageExecutingManager.addListener(result.getId(), executingListener);
        }
      }
    });

    m_suiteExecutingService.getSuiteResultsHeaders(new AsyncCallback<Set<ExecutingResult>>() {
      @Override
      public void onFailure(Throwable caught) {
        m_errorDialog.setMessage(caught);
        m_errorDialog.center();
      }

      @Override
      public void onSuccess(Set<ExecutingResult> list) {
        List<ExecutingResult> results = new LinkedList<ExecutingResult>(list);
        view.addResultToWidget(results);
        for (ExecutingResult result : list) {
          suiteExecutingManager.addResultToListen((SuiteExecutingResult)result);
          suiteExecutingManager.addListener(result.getId(), executingListener);
        }
      }
    });
  }
}
